/*
 * Copyright (c) 2017-2021, Lindenis Tech. Ltd.
 * All rights reserved.
 *
 * File:
 *
 * Description:
 *
 * Author:
 *      xiaoshujun@lindeni.com
 *
 * Create Date:
 *      2021/03/16
 *
 * History:
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <sys/prctl.h>

#include "osal_log.h"
#include "osal_common.h"
#include "lindcomponent.h"
#include "lindesplayer.h"

#include "lindsource.h"
#include "lindnet.h"

#define DISABLE_VDEC 0

#define SAVE_FILE 0
#if SAVE_FILE
FILE * g_fd = 0;
#ifdef MELIS_OS
char * g_filepath = "/mnt/E/1.h264";
#else
char * g_filepath = "/tmp/1.h264";
#endif
#endif

typedef struct _sample_lindsource_ctx_t
{
    lindsource_t *          p_source;
    rtpsource_config_t      rtp_cfg;

    es_player_handle_t      h_esplayer;
} sample_lindsource_ctx_t;

static int _lindsource_data_cb(void * user, av_frame2_t * p_frame, void * ext1, void * ext2)
{
    sample_lindsource_ctx_t * p_ctx = (sample_lindsource_ctx_t *)user;
    char * nal = p_frame->data[0];
    int nal_size = p_frame->size[0];
    switch (p_frame->format) {
        case VFRAME_FORMAT_ES_H264:
        {
#if SAVE_FILE
            fwrite(nal, nal_size, 1, g_fd);
#endif
            logv("get frame format: %d, size: %d", p_frame->format, nal_size);
#if (DISABLE_VDEC == 0)
            esplayer_send_es(p_ctx->h_esplayer, nal, nal_size);
#endif
            break;
        }
        default:
        {
            loge("unknown format: %d", p_frame->format);
            break;
        }
    }

    return 0;
}

int test_rtpsource(sample_lindsource_ctx_t * p_ctx)
{
    int ret = 0;

#if (DISABLE_VDEC == 0)
    // start esplayer
    p_ctx->h_esplayer = esplayer_create();
    if (!p_ctx->h_esplayer)
    {
        goto _exit1_;
    }

    lindesplayer_config_t config = {0};
    config.venc_type = p_ctx->rtp_cfg.enc_type;
    esplayer_set_parameters(p_ctx->h_esplayer, &config);

    esplayer_prepare(p_ctx->h_esplayer);
#endif

    // start rtpsink
    p_ctx->p_source = lindsource_create(LINDSOURCE_RTP, &p_ctx->rtp_cfg);
    if (!p_ctx->p_source)
    {
        loge("lindsource_create failed");
        return -1;
    }

    prctl(PR_SET_NAME, (unsigned long)"main", 0, 0, 0);

    while(1)
    {
#ifdef MELIS_OS
        sleep(10);
#else
        signed char key_val;
        ret = wait_input_char(&key_val, 100000);
        if (ret < 0)
        {
            break;
        }
        else if (ret == 0)
        {
            continue;
        }

        if (key_val > 0 && key_val)
        {
            if (key_val != '\n')
            {
                printf("********* key_val: %c ********** \n", key_val);
            }

            if (key_val == 'q' || key_val == 'Q')
            {
                break;
            }
        }
#endif
    }

_exit2_:
    p_ctx->p_source->close(p_ctx->p_source);

_exit1_:
#if (DISABLE_VDEC == 0)
    esplayer_destroy(p_ctx->h_esplayer);
#endif

    return 0;
}

static void _lindrtp_print_usage(char * this)
{
    printf("\033[32m");
    printf("Usage: \n");
    printf("    %s <options> \n", this);
    printf("        -i [ip]         : the ip addr of the rtp stream receiver \n");
    printf("        -p [port]       : the port of the rtp stream receiver, default '9980' \n");
    printf("        -pt [payload]   : payload type, default '96' \n");
    printf("        -udp/-rdt       : use udp or rdt protocol, default 'udp' \n");
    printf("                        : If use 'rdt' protocol, should run 'sample_lindsource' before 'sample_lindsink'. \n");
    printf("        -h264/-h265     : video encode type, default 'h264' \n");
    printf("    such as: %s -i 192.168.1.2 -p 9980 -rdt \n\n", this);
    printf("\033[0m\n");
}

#ifdef MELIS_OS
static int main_melis(int argc, char **argv)
#else
int main(int argc, char **argv)
#endif
{
    int ret = 0;
    int i = 0;
    sample_lindsource_ctx_t context = {0};
    int port = 0;
    char * ip = NULL;

    if ((argc == 2)
        && (!strcmp(argv[1], "-h")))
    {
        _lindrtp_print_usage(argv[0]);
        return 0;
    }

    strcpy(context.rtp_cfg.ip, "0.0.0.0");
    context.rtp_cfg.port = 9980;
    context.rtp_cfg.enc_type = AV_ENC_TYPE_H264;
    context.rtp_cfg.protocol = LINDNET_TYPE_UDP;
    context.rtp_cfg.payload_type = 96;
    context.rtp_cfg.mtu = 1400;
    context.rtp_cfg.user = &context;
    context.rtp_cfg.output = _lindsource_data_cb;

    for (i = 1; i < argc; )
    {
        if (!strcmp(argv[i], "-i"))
        {
            strcpy(context.rtp_cfg.ip, argv[i+1]);
            i += 2;
        }
        else if (!strcmp(argv[i], "-p"))
        {
            context.rtp_cfg.port = atoi(argv[i+1]);
            i += 2;
        }
        else if (!strcmp(argv[i], "-pt"))
        {
            context.rtp_cfg.payload_type = atoi(argv[i+1]);
            i += 1;
        }
        else if (!strcmp(argv[i], "-rdt"))
        {
            context.rtp_cfg.protocol = LINDNET_TYPE_RDT;
            i += 1;
        }
        else if (!strcmp(argv[i], "-udp"))
        {
            context.rtp_cfg.protocol = LINDNET_TYPE_UDP;
            i += 1;
        }
        else if (!strcmp(argv[i], "-h264"))
        {
            context.rtp_cfg.enc_type = AV_ENC_TYPE_H264;
            i += 1;
        }
        else if (!strcmp(argv[i], "-h265"))
        {
            context.rtp_cfg.enc_type = AV_ENC_TYPE_H265;
            i += 1;
        }
        else
        {
            i++;
        }
    }

#if SAVE_FILE
    g_fd = fopen(g_filepath, "wb+");
    if (NULL == g_fd)
    {
        loge("Open %s file error", g_filepath);
        return -1;
    }
#endif

    test_rtpsource(&context);

#if SAVE_FILE
    if (NULL != g_fd)
    {
        fclose(g_fd);
        g_fd = NULL;
    }
#endif

    return 0;
}

#ifdef MELIS_OS
FINSH_FUNCTION_EXPORT_ALIAS(main_melis, __cmd_sample_lindsource, lindsource sample);
#endif

